/**
 * 
 */
package com.module.hq.ui.mono.heroviewer.widgets;

import java.awt.Point;

import com.dalonedrau.jogl.engine.Condition;
import com.dalonedrau.jogl.engine.GlobalConsts;
import com.dalonedrau.jogl.engine.Interface;
import com.dalonedrau.jogl.engine.JOGLErrorHandler;
import com.dalonedrau.jogl.opengl.sprite.BasicSpriteObject;
import com.dalonedrau.jogl.opengl.sprite.SpriteBase;
import com.dalonedrau.jogl.opengl.sprite.SpriteImageObject;
import com.dalonedrau.jogl.opengl.sprite.SpriteImageObjectFactory;
import com.dalonedrau.jogl.opengl.ui.Button;
import com.dalonedrau.jogl.opengl.ui.GuiComponent;
import com.dalonedrau.jogl.opengl.ui.Label;
import com.dalonedrau.jogl.opengl.ui.UIFactory;
import com.dalonedrau.jogl.opengl.ui.border.Abstract8ImageNoBackgroundBorder;
import com.dalonedrau.jogl.opengl.ui.panel.LandscapePagePanel;
import com.dalonedrau.jogl.opengl.ui.panel.Panel;
import com.dalonedrau.jogl.opengl.ui.panel.PortraitPagePanel;
import com.dalonedrau.jogl.opengl.ui.panel.TabbedPanel;
import com.dalonedrau.jogl.opengl.ui.panel.ThreeStateButton;
import com.dalonedrau.jogl.util.UtilityMethods;
import com.dalonedrau.pool.PooledStringBuilder;
import com.dalonedrau.pool.StringBuilderPool;
import com.dalonedrau.watchable.Watchable;
import com.dalonedrau.watchable.Watcher;
import com.module.hq.bus.globals.HQGlobals;
import com.module.hq.engine.HQCharacter;
import com.module.hq.engine.HQEquipment;
import com.module.hq.engine.HQInteractiveObject;
import com.module.hq.engine.HQInventory;

/**
 * UI Viewer class for the {@link HQCharacter} class.
 * @author DaLoneDrau
 */
public final class HQHeroViewer extends PortraitPagePanel
		implements Watcher {
	/** the singleton instance of {@link HQHeroViewer}. */
	private static HQHeroViewer	instance;
	/**
	 * Gets the one and only instance of {@link HQHeroViewer}.
	 * @return {@link HQHeroViewer}
	 */
	public static HQHeroViewer getInstance() {
		if (HQHeroViewer.instance == null) {
			HQHeroViewer.instance = new HQHeroViewer();
		}
		return HQHeroViewer.instance;
	}
	/** the {@link HQHeroViewer} being viewed. */
	private HQInteractiveObject	pc;
	private Panel				pnlNameEquip;
	private Panel				pnlNameSpells;
	private Panel				pnlNameStats;
	/** the tabbed panel displaying the stats, inventory, and spells panels. */
	private TabbedPanel			tabbedPanel;
	/** the stats panel. */
	// private StatsPanel pnlStats;
	/** Creates a new instance of {@link HQHeroViewer}. */
	private HQHeroViewer() {
		super(Panel.PORTRAIT_CENTER);
		// super.setBorder(new HQMonoHeroViewerBorder());
		try {
			init();
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	/**
	 * Adds a spell to the hero's knowledge.
	 * @param spellId the spell's id
	 */
	public void addSpellToHerosKnowledge(final int spellId) {
		pc.getPCData().addSpellAvailable(spellId);
	}
	/**
	 * Create the tabbed panel containing the hero's stats, inventory, and
	 * spells.
	 * @return {@link Panel}
	 * @throws Exception if an error occurs
	 */
	private Panel createTabbedPanel() throws Exception {
		pnlNameStats = getNamePanel();
		pnlNameEquip = getNamePanel();
		pnlNameSpells = getNamePanel();
		// fix heights
		int maxWidth = 0, maxHeight = 0;
		// get max for stats panel
		maxWidth = StatsPanel.getInstance().getPreferredSize().width;
		maxHeight = StatsPanel.getInstance().getPreferredSize().height;
		// get max for inv panel
		maxWidth = Math.max(maxWidth,
				HQInventory.getInstance().getPreferredSize().width);
		maxHeight = Math.max(maxHeight,
				HQInventory.getInstance().getPreferredSize().height);
		// get max for spells panel
		maxWidth = Math.max(maxWidth,
				HQSpellPanel.getInstance().getPreferredSize().width);
		maxHeight = Math.max(maxHeight,
				HQSpellPanel.getInstance().getPreferredSize().height);
		// get max width for name panel
		maxWidth = Math.max(maxWidth, pnlNameStats.getPreferredSize().width);
		maxHeight = Math.max(maxHeight, pnlNameStats.getPreferredSize().height);

		Panel pnlStats = null, pnlInv = null, pnlSpells = null;
		if (StatsPanel.getInstance().getPreferredSize().width < maxWidth
				|| StatsPanel.getInstance().getPreferredSize().height
				< maxHeight) {
			// add padding
			int neededWidth = maxWidth
					- StatsPanel.getInstance().getPreferredSize().width;
			int neededHeight = maxHeight
					- StatsPanel.getInstance().getPreferredSize().height;
			if (neededWidth > neededHeight) {
				pnlStats = new LandscapePagePanel(Panel.LANDSCAPE_CENTER);
				pnlStats.addChild(pnlNameStats);
				pnlStats.addChild(UIFactory.getInstance().getSpacer(1, 3));
				int w1 = neededWidth / 2, w2 = neededWidth - w1;
				int h1 = Math.max(1, maxHeight);
				pnlStats.addChild(UIFactory.getInstance().getSpacer(w1, h1));
				pnlStats.addChild(StatsPanel.getInstance());
				pnlStats.addChild(UIFactory.getInstance().getSpacer(w2, h1));
			} else {
				pnlStats = new PortraitPagePanel(Panel.PORTRAIT_CENTER);
				pnlStats.addChild(pnlNameStats);
				pnlStats.addChild(UIFactory.getInstance().getSpacer(1, 3));
				pnlStats.addChild(getLabelPanel("Character"));
				pnlStats.addChild(UIFactory.getInstance().getSpacer(1, 3));
				int h1 = neededHeight / 2, h2 = neededHeight - h1;
				int w1 = Math.max(1, maxWidth);
				pnlStats.addChild(UIFactory.getInstance().getSpacer(w1, h1));
				pnlStats.addChild(StatsPanel.getInstance());
				pnlStats.addChild(UIFactory.getInstance().getSpacer(w1, h2));
			}
		} else {
			pnlStats = new PortraitPagePanel(Panel.PORTRAIT_CENTER);
			pnlStats.addChild(pnlNameStats);
			pnlStats.addChild(UIFactory.getInstance().getSpacer(1, 3));
			pnlStats.addChild(getLabelPanel("Character"));
			pnlStats.addChild(UIFactory.getInstance().getSpacer(1, 3));
			pnlStats.addChild(StatsPanel.getInstance());
		}
		if (HQInventory.getInstance().getPreferredSize().width < maxWidth
				|| HQInventory.getInstance().getPreferredSize().height
				< maxHeight) {
			// add padding
			int neededWidth = maxWidth
					- HQInventory.getInstance().getPreferredSize().width;
			int neededHeight = maxHeight
					- HQInventory.getInstance().getPreferredSize().height;
			if (neededWidth > neededHeight) {
				pnlInv = new LandscapePagePanel(Panel.LANDSCAPE_CENTER);
				pnlInv.addChild(pnlNameEquip);
				pnlInv.addChild(UIFactory.getInstance().getSpacer(1, 3));
				int w1 = neededWidth / 2, w2 = neededWidth - w1;
				int h1 = Math.max(1, maxHeight);
				pnlInv.addChild(UIFactory.getInstance().getSpacer(w1, h1));
				pnlInv.addChild(HQInventory.getInstance());
				pnlInv.addChild(UIFactory.getInstance().getSpacer(w2, h1));
			} else {
				pnlInv = new PortraitPagePanel(Panel.PORTRAIT_CENTER);
				pnlInv.addChild(pnlNameEquip);
				pnlInv.addChild(UIFactory.getInstance().getSpacer(1, 3));
				pnlInv.addChild(getLabelPanel("INVENTORY"));
				pnlInv.addChild(UIFactory.getInstance().getSpacer(1, 3));
				int h1 = neededHeight / 2, h2 = neededHeight - h1;
				int w1 = Math.max(1, maxWidth);
				pnlInv.addChild(UIFactory.getInstance().getSpacer(w1, h1));
				pnlInv.addChild(HQInventory.getInstance());
				pnlInv.addChild(UIFactory.getInstance().getSpacer(w1, h2));
			}
		} else {
			pnlInv = new PortraitPagePanel(Panel.PORTRAIT_CENTER);
			pnlInv.addChild(pnlNameEquip);
			pnlInv.addChild(UIFactory.getInstance().getSpacer(1, 3));
			pnlInv.addChild(getLabelPanel("INVENTORY"));
			pnlInv.addChild(UIFactory.getInstance().getSpacer(1, 3));
			pnlInv.addChild(HQInventory.getInstance());
		}
		if (HQSpellPanel.getInstance().getPreferredSize().width < maxWidth
				|| HQSpellPanel.getInstance().getPreferredSize().height
				< maxHeight) {
			// add padding
			int neededWidth = maxWidth
					- HQSpellPanel.getInstance().getPreferredSize().width;
			int neededHeight = maxHeight
					- HQSpellPanel.getInstance().getPreferredSize().height;
			if (neededWidth > neededHeight) {
				pnlSpells = new LandscapePagePanel(Panel.LANDSCAPE_CENTER);
				pnlSpells.addChild(pnlNameSpells);
				pnlSpells.addChild(UIFactory.getInstance().getSpacer(1, 3));
				int w1 = neededWidth / 2, w2 = neededWidth - w1;
				int h1 = Math.max(1, maxHeight);
				pnlSpells.addChild(UIFactory.getInstance().getSpacer(w1, h1));
				pnlSpells.addChild(HQSpellPanel.getInstance());
				pnlSpells.addChild(UIFactory.getInstance().getSpacer(w2, h1));
			} else {
				pnlSpells = new PortraitPagePanel(Panel.PORTRAIT_CENTER);
				pnlSpells.addChild(pnlNameSpells);
				pnlSpells.addChild(UIFactory.getInstance().getSpacer(1, 3));
				pnlSpells.addChild(getLabelPanel("SPELLS"));
				pnlSpells.addChild(UIFactory.getInstance().getSpacer(1, 3));
				int h1 = neededHeight / 2, h2 = neededHeight - h1;
				int w1 = Math.max(1, maxWidth);
				pnlSpells.addChild(UIFactory.getInstance().getSpacer(w1, h1));
				pnlSpells.addChild(HQSpellPanel.getInstance());
				pnlSpells.addChild(UIFactory.getInstance().getSpacer(w1, h2));
			}
		} else {
			pnlSpells = new PortraitPagePanel(Panel.PORTRAIT_CENTER);
			pnlSpells.addChild(pnlNameSpells);
			pnlSpells.addChild(UIFactory.getInstance().getSpacer(1, 3));
			pnlSpells.addChild(getLabelPanel("SPELLS"));
			pnlSpells.addChild(UIFactory.getInstance().getSpacer(1, 3));
			pnlSpells.addChild(HQSpellPanel.getInstance());
		}
		// left side tabs
		tabbedPanel = new TabbedPanel(Panel.PAGELAYOUT_PORTRAIT, true);
		tabbedPanel.addTab(
				getStatisticsTabButton(),
				pnlStats,
				"stats"
				);
		tabbedPanel.addTab(
				getInventoryTabButton(),
				pnlInv,
				"inv"
				);
		tabbedPanel.addTab(
				getSpellsTabButton(),
				pnlSpells,
				"spells"
				);
		tabbedPanel.setBorder(
				HQGlobals.HQ_MONO_CHARVIEWER_BORDER,
				new float[][] {
						HQGlobals.COL_HQ_MONO_DESC_BACKGROUND,
						HQGlobals.COL_HQ_MONO_DESC_BACKGROUND,
						HQGlobals.COL_HQ_MONO_DESC_BACKGROUND
				},
				// tab insets
				new int[] { GlobalConsts.INT_006, GlobalConsts.INT_006,
						GlobalConsts.INT_006, GlobalConsts.INT_006 },
						// content insets
				new int[] { GlobalConsts.INT_009, GlobalConsts.INT_009,
								GlobalConsts.INT_006, GlobalConsts.INT_009 }
				);
		return tabbedPanel;
	}
	/**
	 * Gets the inventory tab button.
	 * @return {@link ThreeStateButton}
	 * @throws Exception if an error occurs
	 */
	private ThreeStateButton getInventoryTabButton() throws Exception {
		SpriteBase sb = new BasicSpriteObject();
		SpriteImageObject img =
				SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_equip_sml");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Label lbl1 = new Label(sb);

		sb = new BasicSpriteObject();
		img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_equip_lrg");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Button btn2 = new Button(sb);
		btn2.setTooltipText("inventory");

		sb = new BasicSpriteObject();
		img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_equip_act");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Label lbl3 = new Label(sb);
		ThreeStateButton btn3S = new ThreeStateButton(lbl1, btn2, lbl3);
		btn3S.setCanStayOn3(new Condition() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public boolean passes() {
				return HQInventory.getInstance().isVisible();
			}
		});
		btn3S.setHorizontalAlignment(GuiComponent.RIGHT);
		return btn3S;
	}
	/**
	 * Gets the name panel.
	 * @return {@link Panel}
	 * @throws Exception if an error occurs
	 */
	private Panel getNamePanel() throws Exception {
		Panel pnl = new LandscapePagePanel(Panel.LANDSCAPE_CENTER);
		pnl.setBorder(new Abstract8ImageNoBackgroundBorder(
					new int[] {
							GlobalConsts.INT_003, GlobalConsts.INT_003,
							GlobalConsts.INT_003, GlobalConsts.INT_003
							}, // insets
				HQGlobals.HQ_MONO_NAMEPANEL_BORDER)
					);
		// 32px
		SpriteBase sb = new BasicSpriteObject();
		SpriteImageObject img =
				SpriteImageObjectFactory.getInstance().getImageByName(
						"ultima_barbarian_zull");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Label lblSprite = new Label(sb);
		pnl.addChild(lblSprite);
		Label lblName = UIFactory.getInstance().getStandardH1Label(
				" \n ");
		// set width to max of 9 characters
		lblName.setPreferredWidth(GlobalConsts.INT_009
				* UIFactory.getInstance().getH1FontCharacterMetrics().width);
		pnl.addChild(lblName);
		return pnl;
	}
	/**
	 * Gets the name panel.
	 * @return {@link Panel}
	 * @throws Exception if an error occurs
	 */
	private Panel getLabelPanel(final String text) throws Exception {
		Panel pnl = new LandscapePagePanel(Panel.LANDSCAPE_CENTER);
		pnl.setBorder(new Abstract8ImageNoBackgroundBorder(
					new int[] {
							GlobalConsts.INT_003, GlobalConsts.INT_003,
							GlobalConsts.INT_003, GlobalConsts.INT_003
							}, // insets
				HQGlobals.HQ_MONO_NAMEPANEL_BORDER)
					);
		Label lbl = UIFactory.getInstance().getTitleLabel(text);
		pnl.addChild(lbl);
		return pnl;
	}
	/**
	 * Gets the pc being viewed.
	 * @return {@link HQInteractiveObject}
	 */
	protected HQInteractiveObject getPc() {
		return pc;
	}
	/**
	 * Gets the spells tab button.
	 * @return {@link ThreeStateButton}
	 * @throws Exception if an error occurs
	 */
	private ThreeStateButton getSpellsTabButton() throws Exception {
		SpriteBase sb = new BasicSpriteObject();
		SpriteImageObject img =
				SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_mag_sml");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Label lbl1 = new Label(sb);
		lbl1.setInactiveImage(
				SpriteImageObjectFactory.getInstance().getImageRefId(
						"hq_ultima_icon_mag_inact"));

		sb = new BasicSpriteObject();
		img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_mag_lrg");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Button btn2 = new Button(sb);
		btn2.setTooltipText("spells");

		sb = new BasicSpriteObject();
		img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_mag_act");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Label lbl3 = new Label(sb);
		ThreeStateButton btn3S = new ThreeStateButton(lbl1, btn2, lbl3);
		btn3S.setCanStayOn3(new Condition() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public boolean passes() {
				return HQSpellPanel.getInstance().isVisible();
			}
		});
		btn3S.setHorizontalAlignment(GuiComponent.RIGHT);
		return btn3S;
	}
	/**
	 * Gets the statistics tab button.
	 * @return {@link ThreeStateButton}
	 * @throws Exception if an error occurs
	 */
	private ThreeStateButton getStatisticsTabButton() throws Exception {
		SpriteBase sb = new BasicSpriteObject();
		SpriteImageObject img =
				SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_stats_sml");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Label lbl1 = new Label(sb);

		sb = new BasicSpriteObject();
		img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_stats_lrg");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Button btn2 = new Button(sb);
		btn2.setTooltipText("Character panel");

		sb = new BasicSpriteObject();
		img = SpriteImageObjectFactory.getInstance().getImageByName(
						"hq_ultima_icon_stats_act");
		sb.setImageRefId(img.getRefId());
		sb.setWidth(img.getWidth());
		sb.setHeight(img.getHeight());
		Label lbl3 = new Label(sb);
		ThreeStateButton btn3S = new ThreeStateButton(lbl1, btn2, lbl3);
		btn3S.setCanStayOn3(new Condition() {
			/**
			 * {@inheritDoc}
			 */
			@Override
			public boolean passes() {
				return StatsPanel.getInstance().isVisible();
			}
		});
		btn3S.setHorizontalAlignment(GuiComponent.RIGHT);
		return btn3S;
	}
	/**
	 * Initializes the viewer.
	 * @throws Exception if an error occurs
	 */
	private void init() throws Exception {
		// 1st row - Sprite, Name
		// super.addChild(createNamePanel());
		// 2nd row stats/inv/spells
		super.addChild(createTabbedPanel());
		// 2nd row - description
		// super.addChild(createDescriptionPanel());
		tabbedPanel.showTab("inv");
	}
	/**
	 * Sets the character being viewed.
	 * @param newPc the {@link HQCharacter} to set
	 */
	public void setPc(final HQInteractiveObject newPc) {
		if (pc != null
				&& pc.hasIOFlag(HQGlobals.IO_01_PC)) {
			pc.getPCData().removeWatcher(this);
		}
		pc = newPc;
		pc.getPCData().addWatcher(this);
		pc.getPCData().clearSpellsAvailable();
		HQInventory.getInstance().setPlayerViewed(pc);
		HQSpellPanel.getInstance().setPlayerViewed(pc);
		if (pc.getPCData().isMagician()) {
			tabbedPanel.getTab(2).setActive(true);
		} else {
			tabbedPanel.getTab(2).setActive(false);
		}
		tabbedPanel.showTab("stats");
		watchUpdated(null);
		/*
		if (pc.getPCData().isMagician()) {
			// show spell chooser
			if (pc.getPCData().getProfession() == HQGlobals.CLASS_02ELF) {
				SpellFamilyChooserDialog.getInstance().setNumAllowed(1);
			} else {
				SpellFamilyChooserDialog.getInstance().setNumAllowed(
						GlobalConsts.INT_003);
			}
			Point pt = UtilityMethods.getInstance().centerComponentInFrame(
					SpellFamilyChooserDialog.getInstance());
			SpellFamilyChooserDialog.getInstance().setPosition(
					pt.x, pt.y, 1000);
			Interface.getInstance().showDialog(
					SpellFamilyChooserDialog.getInstance());
		}*/
		try {
		System.out.println(pc.getPCData().getName()+"::wpn::"
				+HQEquipment.getInstance().getPlayerWeaponType(pc));
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void watchUpdated(final Watchable data) {
		// char sprites
		Label lblSprite = (Label) pnlNameEquip.getChildren()[0];
		lblSprite.getSprite().setImageRefId(pc.getPCData().getSpriteRef());
		lblSprite = (Label) pnlNameSpells.getChildren()[0];
		lblSprite.getSprite().setImageRefId(pc.getPCData().getSpriteRef());
		lblSprite = (Label) pnlNameStats.getChildren()[0];
		lblSprite.getSprite().setImageRefId(pc.getPCData().getSpriteRef());
		lblSprite = null;
		// name
		PooledStringBuilder sb =
				StringBuilderPool.getInstance().getStringBuilder();
		sb.append(pc.getPCData().getName());
		sb.append(" the ");
		sb.append(HQGlobals.CLASS_TITLES[pc.getPCData().getProfession()]);
		Label lblName = (Label) pnlNameEquip.getChildren()[1];
		lblName.setText(sb.toString());
		lblName = (Label) pnlNameSpells.getChildren()[1];
		lblName.setText(sb.toString());
		lblName = (Label) pnlNameStats.getChildren()[1];
		lblName.setText(sb.toString());
		lblName = null;
		sb.setLength(0);
		sb.returnToPool();
		StatsPanel.getInstance().update(pc.getPCData());
	}

}
